package com.longrise.android.widget;

import android.content.Context;
import android.graphics.Color;
import android.os.Environment;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.longrise.LEAP.Base.Objects.EntityBean;
import com.longrise.android.FrameworkManager;
import com.longrise.android.UIManager;
import com.longrise.android.database.LDBHelper;
import com.longrise.android.database.table.moduleTable;
import com.longrise.android.widget.LDownloadFileProgressView.LFileOpenType;
import com.longrise.android.widget.LDownloadFileProgressView.OnLDownloadFileProgressViewDownloadErrorListener;
import com.longrise.android.widget.LDownloadFileProgressView.OnLDownloadFileProgressViewDownloadFinishListener;
import com.longrise.ormlite.stmt.QueryBuilder;
import com.longrise.serializer.apache.commons.codec.binary.Hex;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.security.MessageDigest;

public class LModuleView extends LinearLayout implements OnLDownloadFileProgressViewDownloadFinishListener, OnLDownloadFileProgressViewDownloadErrorListener
{
	private Context _context = null;
	private float _density = 1f;
	
	private TextView _title = null;
	private LDownloadFileProgressView _downview = null;
	
	private String _moduleName = null;
	private String _basemoduleName = null;
	private String _classPath = null;
	private EntityBean _config = null;
	private String _tipsText = "模型加载失败";
	
	private OnLModuleViewFinishListener _finishListener = null;
	
	
	private void init()
	{
		try
		{
			this._density = FrameworkManager.getInstance().getDensity();
			this.setOrientation(LinearLayout.VERTICAL);			
			if(null!=this._context)
			{		
				this._title = new TextView(this._context);
				if(null!=this._title)
				{
					this._title.setTextSize(UIManager.getInstance().FontSize14);
					this._title.setTextColor(Color.parseColor("#2f2f2f"));
					this._title.setVisibility(View.GONE);
					this.addView(this._title, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
				}
				this._downview = new LDownloadFileProgressView(this._context);
				if(null!=this._downview)
				{
					this._downview.setOpenType(LFileOpenType.Never);
					this._downview.setButtomVisibility(View.GONE);
					this._downview.setVisibility(View.GONE);
					this._downview.setFileDir(Environment.getExternalStorageDirectory().getPath()+"/"+FrameworkManager.getInstance().getAppdir()+"/system/modules/");
					this.addView(this._downview, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
				}				
			}
			this.regEvent(true);
		}
		catch(Exception ex){}
		finally
		{			
		}
	}
	
	private void regEvent(boolean b) 
	{
		if(null!=this._downview)
		{
			this._downview.setOnLDownloadFileProgressViewDownloadFinishListener(b?this:null);
			this._downview.setOnLDownloadFileProgressViewDownloadErrorListener(b?this:null);
		}
	}
	
	private String getMD5(String filepath)
	{
		MessageDigest md5 = null;
		File f = null;
		FileInputStream stream = null;
		byte[] buffer = null;
		int length = 0;
		String md5str = null;
		try
		{
			if(null!=filepath && !"".equals(filepath))
			{
				md5 = MessageDigest.getInstance("MD5");
				if(null!=md5)
				{
					f = new File(filepath);
					if(null!=f && f.exists() && f.isFile())
					{
						stream = new FileInputStream(f);
						if(null!=stream)
						{
							buffer = new byte[8192];
							if(null!=buffer)
							{
								 while((length = stream.read(buffer)) != -1) 
								 {
									 md5.update(buffer, 0, length);
						         }
								 md5str = new String(Hex.encodeHex(md5.digest()));
							}
							stream.close();
						}
					}
				}
			}
			return md5str;
		}
		catch(Exception ex){}
		finally
		{
			filepath = null;
			f = null;
			md5 = null;
			stream = null;
			buffer = null;
		}
		return null;
	}
	
	private boolean checkmd5(moduleTable table)
	{
		String md5str = null;
		try
		{
			if(null!=table)
			{
				if(null!=table.getVercode() && !"".equals(table.getVercode()))
				{
					md5str = this.getMD5(table.getFilepath());
					if(null!=md5str && !"".equals(md5str))
					{							
						if(md5str.equals(table.getVercode()))
						{
							return true;
						}
					}
				}
			}
		}
		catch (Exception ex) {}
		finally
		{
			table = null;
			md5str = null;
		}
		return false;
	}
	private boolean saveTable(String moduleName, String filepath) 
	{
		moduleTable table = null;
		try
		{
			if(null!=this._context && null!=filepath && !"".equals(filepath))
			{
				
				table = this.getModuleTable(moduleName);				
				if(null!=table)
				{
					table.setFilepath(filepath);
					if(this.checkmd5(table))
					{
						table.setRedownloadtype(0);					
						if(2==table.getType())
						{
							table.setIntother(1<<1|table.getIntother());
						}					
						LDBHelper.update(this._context, moduleTable.class, table);
						return true;
					}
				}
			}
		}
		catch(Exception ex){}
		finally
		{
			filepath = null;
			table = null;
		}
		return false;
	}
	
	private moduleTable getModuleTable(String moduleName)
	{
		QueryBuilder<moduleTable,?> query = null;
		try
		{
			if(null!=this._context && null!=moduleName && !"".equals(moduleName))
			{
				query = LDBHelper.getQueryBuilder(this._context,moduleTable.class);
				if(null!=query)
				{
					query.where().eq("name", moduleName);
					return LDBHelper.queryForFirst(this._context, moduleTable.class, query.prepare());
				}
			}
		}
		catch(Exception ex){}
		finally
		{
			moduleName = null;
			query = null;
		}
		return null;
	}
	
	public void setProgressVisibility(int visibility)
    {
    	if(null!=this._downview)
    	{
    		this._downview.setProgressVisibility(visibility);
    	}
    }
    
    public void setSpeedVisibility(int visibility)
    {
    	if(null!=this._downview)
    	{
    		this._downview.setSpeedVisibility(visibility);
    	}
    }

	/**
	 * 根据路径加载类
	 * @param classpath
	 * @return
	 */
	public Object loadModule(String classpath)
	{
		if(classpath == null || classpath.isEmpty())
		{
			return null;
		}

		Class<?> c = null;
		Constructor constructor;
		try
		{

			c = Class.forName(classpath);
			if(c != null)
			{
				constructor = c.getConstructor(Context.class);
				if(null != constructor)
				{
					return constructor.newInstance(_context);
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

		return null;
	}

	public void loadModule(String moduleName, String basemoduleName, String classpath)
	{
		Object obj = null;
		moduleTable table = null;
		File f = null;
		String downString = null;
		String [] baseNames = null;
		try
		{
			this._moduleName = moduleName;
			this._basemoduleName = basemoduleName;
			this._classPath = classpath;
			if(null!=this._context && null!=this._moduleName && !"".equals(this._moduleName)&& null!=this._classPath && !"".equals(this._classPath))
			{
				downString = this._moduleName.trim();
				if(null!=this._basemoduleName && !"".equals(this._basemoduleName))
				{
					downString = this._basemoduleName.trim() + "|" + downString;
				}
				baseNames = downString.split("\\|");
				if(null!=baseNames && 0<baseNames.length)
				{
					for(int i=0;i<baseNames.length;i++)
					{
						table = this.getModuleTable(baseNames[i]);
						if(null!=table)
						{
							if(null!=table.getFilepath() && !"".equals(table.getFilepath()))
							{
								f = new File(table.getFilepath());
								if(null!=f)
								{
									if(f.exists() && f.isFile())
									{
										if(!this.checkmd5(table))
										{
											table.setRedownloadtype(1);
										}
									}
									else
									{
										table.setRedownloadtype(1);
									}
								}
							}
							if(1==table.getRedownloadtype())
							{
								if(null!=this._downview && null!=table.getUrl() && !"".equals(table.getUrl()))
								{
									if(null!=f && f.exists())
									{
										f.delete();
										if(0==table.getType())
										{
											table.setIntother(1|table.getIntother());
											LDBHelper.update(this._context, moduleTable.class, table);
										}										
									}									
									this._downview.setUrl(table.getUrl());	
									this._downview.setTag(table.getName());
									this._downview.setFileName(table.getName()+".dex");
									this._downview.setVisibility(View.VISIBLE);
									this._downview.delete();
									this._downview.start();
									return;
								}
							}
						}
					}
				}
				
				obj = FrameworkManager.getInstance().loadModule(this._context, this._moduleName, this._basemoduleName, this._classPath);
				if(null!=obj)
				{
					if(null!=this._finishListener)
					{
						this._finishListener.onLModuleViewFinish(this, obj);
					}
					return;
				}
				
				if(null!=this._finishListener)
				{
					this._finishListener.onLModuleViewFinish(this, null);
				}
				if(null!=this._tipsText && !"".equals(this._tipsText))
				{
					Toast.makeText(this._context, this._tipsText, Toast.LENGTH_SHORT).show();
				}
			}
			
		}
		catch(Exception ex){}
		finally
		{
			f = null;
			obj = null;
			table = null;
			moduleName = null;
			classpath = null;
			downString = null;
			baseNames = null;
		}
	}
	
	public void setOnLModuleViewFinishListener(OnLModuleViewFinishListener listener)
	{
		this._finishListener = listener;
	}
	
	public void setTipsText(String text)
	{
		this._tipsText = text;
	}
	
	public void setTextSize(float size)
	{
		if(null!=this._title)
		{
			this._title.setTextSize(size);
		}
	}
	
	public void setTextColor(int color)
	{
		if(null!=this._title)
		{
			this._title.setTextColor(color);
		}
	}
	
	public void setText(String text)
	{
		try
		{
			if(null!=this._title && null!=text)
			{
				this._title.setText(text);
				this._title.setVisibility(View.VISIBLE);
			}
		}
		catch(Exception ex){}
		finally
		{
			text = null;
		}
	}

	public void setModuleName(String name) 
	{
		this._moduleName = name;		
	}

	public void setClassPath(String path)
	{
		this._classPath = path;
	}
	
	public void setConfig(EntityBean bean)
	{
		this._config = bean;
	}
	public EntityBean getConfig()
	{
		return this._config;
	}
	
	public LModuleView(Context context) 
	{
		super(context);
		this._context = context;
		this.init();
	}
	
	@Override
	public void onLDownloadFileProgressViewDownloadError(View v, String filepath) 
	{
		try
		{
			if(null!=this._downview)
			{
				this._downview.setVisibility(View.GONE);
			}
			if(null!=this._context)
			{
				Toast.makeText(this._context, "模型下载失败", Toast.LENGTH_SHORT).show();
			}
			
			if(null!=this._finishListener)
			{
				//试图加载原来的模型
				this._finishListener.onLModuleViewFinish(this, FrameworkManager.getInstance().loadModule(this._context, this._moduleName, this._basemoduleName, this._classPath));
			}
		}
		catch(Exception ex){}
		finally
		{
			v = null;
			filepath = null;
		}
	}
	@Override
	public void onLDownloadFileProgressViewDownloadFinish(View v, String filepath) 
	{
		try
		{
			if(null!=this._downview)
			{
				this._downview.setVisibility(View.GONE);
			}
			if(this.saveTable(v.getTag().toString(), filepath))
			{
				this.loadModule(this._moduleName, this._basemoduleName, this._classPath);
			}
			else
			{
				if(null!=this._context)
				{
					Toast.makeText(this._context, "数据包验证失败", Toast.LENGTH_SHORT).show();
				}
				if(null!=this._finishListener)
				{
					this._finishListener.onLModuleViewFinish(this, null);
				}
			}
		}
		catch(Exception ex){}
		finally
		{
			v = null;
			filepath = null;
		}
	}
	
	public interface OnLModuleViewFinishListener
	{
		public void onLModuleViewFinish(View v, Object object);
	}

	
}
